package it.polimi.traveldream.web.beans;

import it.polimi.traveldream.managers.CarrelloManager;
import it.polimi.traveldream.managers.CarrelloManager.DataBaseException;
import it.polimi.traveldream.managers.PacchettoManager;
import it.polimi.traveldream.managers.ProductManager;

import it.polimi.traveldream.managers.credentials.UserCredentialManager.UserAlreadyExistsException;
import it.polimi.traveldream.persistence.dtos.PacchettoDTO;
import it.polimi.traveldream.persistence.dtos.HotelProdDTO;
import it.polimi.traveldream.persistence.dtos.PonteHotelPaccDTO;
import it.polimi.traveldream.persistence.dtos.PacchettoPersonalizzatoDTO;
import it.polimi.traveldream.persistence.dtos.PonteTourPaccDTO;
import it.polimi.traveldream.persistence.dtos.PonteTrattaVoloDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneHotelDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneTourDTO;
import it.polimi.traveldream.persistence.dtos.PrenotazioneVoloDTO;
import it.polimi.traveldream.persistence.dtos.TourProdDTO;
import it.polimi.traveldream.web.beans.login.XHTMLPagesConstants;
import it.polimi.traveldream.persistence.dtos.TrattaProdDTO;

import java.io.Serializable;
import java.util.Date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
//import javax.persistence.EntityExistsException;



import org.primefaces.event.CellEditEvent;

//import javax.faces.bean.ViewScoped;

@ManagedBean(name = "packPresBean")
@SessionScoped
public class PackagesPresentationBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -313557987562427867L;
	@EJB
	private PacchettoManager packMng;
	@EJB
	private CarrelloManager carrelloMng;
	@EJB
	private ProductManager prodMng;

	private List<HotelProdDTO> filteredHotel;

	private List<TourProdDTO> filteredTour;

	private List<TrattaProdDTO> filteredVoli;

	private PacchettoDTO pacchetto;

	private int IDPacchetto;

	private List<PonteHotelPaccDTO> ponteHotel;

	private PacchettoPersonalizzatoDTO pacchettoInCarrello;

	private PrenotazioneHotelDTO cancellaHotel;

	private PrenotazioneTourDTO cancellaTour;

	private PrenotazioneVoloDTO cancellaVolo;

	private HotelProdDTO aggiungiHotel;

	private TourProdDTO aggiungiTour;

	private TrattaProdDTO aggiungivolo;

	private List<HotelProdDTO> allHotel;

	private List<TourProdDTO> allTour;

	private List<TrattaProdDTO> allVoli;

	public PrenotazioneTourDTO getCancellaTour() {
		return cancellaTour;
	}

	public void setCancellaTour(PrenotazioneTourDTO cancellaTour) {
		this.cancellaTour = cancellaTour;
	}

	public List<TourProdDTO> getAllTour() {
		return allTour;
	}

	public void setAllTour(List<TourProdDTO> allTour) {
		this.allTour = allTour;
	}

	private Date data;

	public void setPacchetto(PacchettoDTO pack) {
		this.pacchetto = pack;

		this.pacchetto.setHotels(packMng.findHotelInPacchetto(pack
				.getIDPacchetto()));
		this.pacchetto.setPonteHotel(packMng.findPonteHotelInPacchetto(pack
				.getIDPacchetto()));
		this.pacchetto.setPonteTour(packMng.findPonteTourInPacchetto(pack
				.getIDPacchetto()));
		this.pacchetto.setPonteVolo(packMng.findPonteVoloInPacchetto(pack
				.getIDPacchetto()));
		this.ponteHotel = pacchetto.getPonteHotel();
	}

	public PacchettoDTO getPacchetto() {

		return pacchetto;
	}

	public List<PacchettoDTO> getAllPackages() {
		return packMng.findAllPacchetto();
	}
	
	public List<PacchettoDTO> getPubPackages() {
		return packMng.findPubPacchetto();
	}

	public void setIDPacchetto(int id) {
		this.IDPacchetto = id;
	}

	public int getIDPacchetto() {
		return IDPacchetto;
	}

	public List<HotelProdDTO> getHotelsInPackages(int IDPacchetto) {
		return packMng.findHotelInPacchetto(IDPacchetto);
	}

	public PacchettoDTO getDetailPacchetto() {
		return pacchetto;
	}

	public List<PacchettoDTO> getAllPacchetti() {
		return packMng.findAllPacchetto();
	}

	public void deletePaccheto(int pacchetID) {
		try {
			packMng.deletePacchetto(pacchetID);
		} catch (Exception e) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(
					XHTMLPagesConstants.GENERIC_ERROR,
					new FacesMessage(
							"Impossibile elminare il pacchetto. Provare di nuovo."));
			throw new RuntimeException(e);
		}

	}

	public List<PonteHotelPaccDTO> getPonteHotel() {
		return ponteHotel;
	}

	
	public void onCellEdit(CellEditEvent event) {  
        Object oldValue = event.getOldValue();  
        Object newValue = event.getNewValue();  
          
        if(newValue != null && !newValue.equals(oldValue)) {  
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);  
            FacesContext.getCurrentInstance().addMessage(null, msg);  
        }  
	}
	
	public void setData(Date d){
		this.data=d;
	}
	
	
	//gestione aggiungi elementi nel carrello
	
			public PacchettoPersonalizzatoDTO getPacchettoInCarrello(){
				return pacchettoInCarrello;
			}
			
			public void setPacchettoInCarrello(PacchettoPersonalizzatoDTO pack){
				this.pacchettoInCarrello=pack;
			}
			
			public void onLoadFormDettagliPacchetto(){
				pacchettoInCarrello= new PacchettoPersonalizzatoDTO();
				pacchettoInCarrello.setIDPacchettoOriginale(pacchetto.getID());
				System.out.print(pacchetto.getID());
				pacchettoInCarrello.setPrenotazione(0);
				PrenotazioneHotelDTO prenotazione;
				PrenotazioneTourDTO prenTour;
				PrenotazioneVoloDTO prenVolo;
				for(PonteHotelPaccDTO p : pacchetto.getPonteHotel()){
					prenotazione=new PrenotazioneHotelDTO();
					prenotazione.setHotel(p.getHotel());
					prenotazione.setIDPrenotazione(pacchetto.getID());
					prenotazione.setNumeroPersone(p.getNumeroPersone());
					Date date= GregorianCalendar.getInstance().getTime();
					prenotazione.setCheckIN(date);
					prenotazione.setCheckOUT(date);
					pacchettoInCarrello.addPrenotazioneHotel(prenotazione);
				}
				
				for(PonteTourPaccDTO tour : pacchetto.getPonteTour()){
					prenTour=new PrenotazioneTourDTO();
					prenTour.setTour(tour.getTour());
					prenTour.setNumeroPersone(tour.getNumeroPersone());
					prenTour.setIDPrenotazione(pacchetto.getIDPacchetto());
					Date date= GregorianCalendar.getInstance().getTime();
					prenTour.setData(date);
					pacchettoInCarrello.addPrenotazioneTour(prenTour);
				}
				for(PonteTrattaVoloDTO volo: pacchetto.getPonteVolo()){
					prenVolo= new PrenotazioneVoloDTO();
					prenVolo.setIdPrenotazione(pacchetto.getIDPacchetto());
					prenVolo.setNumeroPersone(volo.getNumeroPersone());
					prenVolo.setTrattaVolo(volo.getTrattaVolo());
					Date date= GregorianCalendar.getInstance().getTime();
					prenVolo.setData(date);
					pacchettoInCarrello.addPrenotazioneVolo(prenVolo);
				}
				this.allHotel= prodMng.findAllHotel();
				this.allTour= prodMng.findAllTour();
				this.allVoli= prodMng.findAllTratte();
				//pacchettoInCarrello.setPrenotazioneHotel(pacchetto.getPonteHotel());
				
			}
			
			
	
	//gestione prenotazione hotel
			public void setAggiungiHotel(HotelProdDTO hotel){
				this.aggiungiHotel=hotel;
			}
			
			public HotelProdDTO getAggiungiHotel(){
				return aggiungiHotel;
			}
			
			public void setHotelPrenotazione(List<PrenotazioneHotelDTO> hotels){
				this.pacchettoInCarrello.setHotels(hotels);
			}
			
			public List<PrenotazioneHotelDTO> getHotelPrenotazione(){
				return pacchettoInCarrello.getHotels();
			}
			
			public void setCancellaHotel(PrenotazioneHotelDTO hotel){
				this.cancellaHotel=hotel;
				
			}
			
			public PrenotazioneHotelDTO getCancellaHotel(){
				return cancellaHotel;
			}
			
				//funzioni necessarie per la scelta di un hotel da aggiungere
				public void setFilteredHotel(List<HotelProdDTO> hotels){
					this.filteredHotel=hotels;
				}
				
				public List<HotelProdDTO> getFilteredHotel(){
					return filteredHotel;
				}
				
				public void setAllHotel(List<HotelProdDTO> hotels){
					this.allHotel=hotels;	
				}
				
				public List<HotelProdDTO> getAllHotel(){
					return allHotel;
				}
	
	public Date getData(){
		return data;
	}

	public void delete() {
		pacchettoInCarrello.detetePrenotazioneHotel(cancellaHotel);
	}

	public void aggiungiHotel() {
		PrenotazioneHotelDTO prenotazione = new PrenotazioneHotelDTO();
		prenotazione.setHotel(aggiungiHotel);
		prenotazione.setIDPrenotazione(pacchetto.getID());
		prenotazione.setNumeroPersone(0);
		Date date = GregorianCalendar.getInstance().getTime();
		prenotazione.setCheckIN(date);
		prenotazione.setCheckOUT(date);
		pacchettoInCarrello.addPrenotazioneHotel(prenotazione);
		aggiungiHotel = new HotelProdDTO();
	}

	// gestione prenotazione tour
	public void deleteTour() {
		pacchettoInCarrello.detetePrenotazioneTour(cancellaTour);
	}

	public TourProdDTO getAggiungiTour() {
		return aggiungiTour;
	}

	public void setAggiungiTour(TourProdDTO aggiungiTour) {
		this.aggiungiTour = aggiungiTour;
	}

	public List<TourProdDTO> getFilteredTour() {
		return filteredTour;
	}

	public void setFilteredTour(List<TourProdDTO> filteredTour) {
		this.filteredTour = filteredTour;
	}

	public void aggiungiTour() {
		PrenotazioneTourDTO prenotazione = new PrenotazioneTourDTO();
		prenotazione.setTour(aggiungiTour);
		prenotazione.setIDPrenotazione(pacchetto.getIDPacchetto());
		Date date = GregorianCalendar.getInstance().getTime();
		prenotazione.setData(date);
		prenotazione.setNumeroPersone(0);
		pacchettoInCarrello.addPrenotazioneTour(prenotazione);
		aggiungiTour = new TourProdDTO();
	}

	// gestione prenotazione voli

	public PrenotazioneVoloDTO getCancellaVolo() {
		return cancellaVolo;
	}

	public void setCancellaVolo(PrenotazioneVoloDTO cancellaVolo) {
		this.cancellaVolo = cancellaVolo;
	}

	public TrattaProdDTO getAggiungivolo() {
		return aggiungivolo;
	}

	public void setAggiungivolo(TrattaProdDTO aggiungivolo) {
		this.aggiungivolo = aggiungivolo;
	}

	public List<TrattaProdDTO> getAllVoli() {
		return allVoli;
	}

	public void setAllVoli(List<TrattaProdDTO> allVoli) {
		this.allVoli = allVoli;
	}

	public void deleteAeroporto() {
		pacchettoInCarrello.detetePrenotazioneVolo(cancellaVolo);
	}

	public void aggiungiVolo() {
		PrenotazioneVoloDTO prenotazione = new PrenotazioneVoloDTO();
		prenotazione.setTrattaVolo(aggiungivolo);
		prenotazione.setIdPrenotazione(pacchetto.getID());
		prenotazione.setNumeroPersone(1);
		Date date = GregorianCalendar.getInstance().getTime();
		prenotazione.setData(date);
		pacchettoInCarrello.addPrenotazioneVolo(prenotazione);
		aggiungivolo = new TrattaProdDTO();
	}

	// salva pacchetto personalizzato

	public List<TrattaProdDTO> getFilteredVoli() {
		return filteredVoli;
	}

	public void setFilteredVoli(List<TrattaProdDTO> filteredVoli) {
		this.filteredVoli = filteredVoli;
	}

	public void check(){
		Boolean bTot = false;
		
		if(checkHotelSingoli()){
			if(checkVoliSingoli()){
				if(checkSovrapposizioneHotels()){
					if(checkSovrapHotelVoli()) bTot = true;
				}
			}
		}
		System.out.println(bTot);
		
		
		
		//System.out.println("**** "+b1);
		if(bTot){
			save();
		}
		else{
			FacesContext.getCurrentInstance().addMessage("mex", new FacesMessage(FacesMessage.SEVERITY_INFO,"Impossibile salvare il pacchetto: ", "Ricontrollare i campi inseriti"));
			
		}
	}
	
	public boolean checkHotelSingoli(){
		Boolean bool=true;
		for(PrenotazioneHotelDTO prenH : pacchettoInCarrello.getHotels()){
			if(prenH.getCheckIN().after(prenH.getCheckOUT()) ||  prenH.getCheckIN().equals(prenH.getCheckOUT())) bool=false;
		}
		return bool;
	}
	
	public boolean checkVoliSingoli(){
		Boolean bool=true;
		for(PrenotazioneVoloDTO prenV : pacchettoInCarrello.getVoli()){
			for(PrenotazioneVoloDTO prenV2 : pacchettoInCarrello.getVoli()){
				if(prenV!=prenV2){
				if(prenV.getData().equals(prenV2.getData())) bool=false;
				}
				}
		}
		return bool;
	}
	
	public boolean checkSovrapposizioneHotels(){
		Boolean bool=true;
		for(PrenotazioneHotelDTO prenH1 : pacchettoInCarrello.getHotels()){
			for(PrenotazioneHotelDTO prenH2 : pacchettoInCarrello.getHotels()){
				if(prenH1!=prenH2){
					if((prenH1.getCheckIN().after(prenH2.getCheckIN()) && prenH1.getCheckIN().before(prenH2.getCheckOUT()))
							|| (prenH1.getCheckIN().equals(prenH2.getCheckOUT())) || (prenH1.getCheckOUT().equals(prenH2.getCheckOUT()))||
									(prenH1.getCheckIN().equals(prenH2.getCheckIN()))) bool=false;
				}
			}
		}
		
		return bool;
	}
	
	public boolean checkSovrapHotelVoli(){
		Boolean bool=true;
		for(PrenotazioneVoloDTO prenV : pacchettoInCarrello.getVoli()){
			for(PrenotazioneHotelDTO prenH : pacchettoInCarrello.getHotels()){
				if((prenV.getData().after(prenH.getCheckIN()) && prenV.getData().before(prenH.getCheckOUT()))
						|| (prenV.getData().equals(prenH.getCheckIN())) || (prenV.getData().equals(prenH.getCheckOUT()))
						) bool=false;
			}
		}
		return bool;
	}
	
	
	public String save() {
		System.out.print("sono in salva pacchetto: "
				+ pacchettoInCarrello.getIDPacchettoOriginale());
		try {
			carrelloMng.salvaInCarrello(pacchettoInCarrello);
			System.out.println("e qui ci siamo");
		} catch (DataBaseException p) {
			FacesContext context = FacesContext.getCurrentInstance();
			context.addMessage(XHTMLPagesConstants.SAVE_PACK_CARRELLO, 
			new FacesMessage("Impossibile salvare il pacchetto. Provare di nuovo."));
		}

		return "show_pacchetti.xhtml?faces-redirect=true";
	}

}
